package handler

import (
	"encoding/json"
	"fmt"
	"gitee.com/mangenotwork/game-douniu/api/dao"
	"gitee.com/mangenotwork/game-douniu/api/entity"
	"github.com/mangenotwork/common/log"
	"github.com/mangenotwork/common/utils"
	"sync"
	"time"
)

// 玩家游戏局对象

var GameMatch sync.Map

// 开始游戏
func NewGameMatch(roomId int64) (*entity.GameMatch, error) {

	// 获取房间数据
	roomData, err := RoomData(roomId)
	if err != nil {
		log.Error("获取房间数据失败", err)
		return nil, err
	}

	// 创建游戏
	userList, err := json.Marshal(roomData.UserList)
	if err != nil {
		return nil, err
	}
	gameData, err := new(dao.GameDao).NewGame(&entity.GameInfoData{
		RoomId:    roomId,             // 房间id
		Homeowner: roomData.Homeowner, // 房主的id
		UserList:  string(userList),   // 所有玩家的json
		CreatedAt: time.Now().Unix(),  // 游戏对局创建时间
	})
	if err != nil {
		return nil, err
	}

	gameMatch := &entity.GameMatch{
		GameId:    gameData.GameId,                  // 游戏对局id
		RoomId:    roomId,                           // 房间id
		Homeowner: roomData.Homeowner,               // 房主的id
		UserList:  make([]*entity.GameMatchUser, 0), // 所有玩家
		PlayCount: 0,                                // 当前轮数，累加一 直到玩10轮结束本局游戏
		State:     entity.WaitReadyStage,            // 游戏状态
		Item:      &entity.GameMatchItem{},          // 当前轮
		Ready:     make([]*entity.UserReady, 0),
	}
	for _, v := range roomData.UserList {
		gameMatch.UserList = append(gameMatch.UserList, &entity.GameMatchUser{
			UserId:   v.UserId,
			NickName: v.NickName,
			Vocation: 0, // 玩家庄闲 0:还未定 1:庄  2:闲
			Score:    0, // 分数 总输赢
		})

		isReady := false
		if v.UserId == roomData.Homeowner {
			isReady = true
		}
		gameMatch.Ready = append(gameMatch.Ready, &entity.UserReady{
			UserId:  v.UserId,
			IsReady: isReady,
		})

		// 用户状态记录
		SetUserState(v.UserId, &entity.UserState{State: 2, GameId: gameData.GameId})
	}

	gameKey := utils.AnyToString(gameData.GameId)
	GameMatch.Store(gameKey, gameMatch)

	// 房间设置新的游戏id
	RoomSetGameId(roomId, gameMatch.GameId)

	return gameMatch, nil
}

func GetGameMatchObj(gameId int64) (*entity.GameMatch, error) {
	gameMatchDataObj := &entity.GameMatch{}
	gameKey := utils.AnyToString(gameId)
	gameMatchData, ok := GameMatch.Load(gameKey)
	if !ok {
		return gameMatchDataObj, fmt.Errorf("本局游戏已结束")
	}
	gameMatchDataObj, ok = gameMatchData.(*entity.GameMatch)
	if !ok {
		return gameMatchDataObj, fmt.Errorf("本局游戏已结束")
	}
	return gameMatchDataObj, nil
}

// 游戏准备
func UserReady(gameId, userId int64) (*entity.GameMatch, error) {
	gameMatchDataObj := &entity.GameMatch{}
	gameKey := utils.AnyToString(gameId)
	gameMatchData, ok := GameMatch.Load(gameKey)
	if !ok {
		return gameMatchDataObj, fmt.Errorf("本局游戏已结束")
	}
	gameMatchDataObj, ok = gameMatchData.(*entity.GameMatch)
	if !ok {
		return gameMatchDataObj, fmt.Errorf("本局游戏已结束")
	}

	for i := 0; i < len(gameMatchDataObj.Ready); i++ {
		if gameMatchDataObj.Ready[i].UserId == userId {
			gameMatchDataObj.Ready[i].IsReady = true
		}
	}

	GameMatch.Store(gameKey, gameMatchDataObj)
	return gameMatchDataObj, nil
}

// 房主点击开始选庄闲
func VocationSelectStart(gameId int64) (*entity.GameMatch, error) {
	gameMatchDataObj := &entity.GameMatch{}
	gameKey := utils.AnyToString(gameId)
	gameMatchData, ok := GameMatch.Load(gameKey)
	if !ok {
		return gameMatchDataObj, fmt.Errorf("本局游戏已结束")
	}
	gameMatchDataObj, ok = gameMatchData.(*entity.GameMatch)
	if !ok {
		return gameMatchDataObj, fmt.Errorf("本局游戏已结束")
	}

	// 准备判断
	ready := true
	for _, v := range gameMatchDataObj.Ready {
		if !v.IsReady {
			ready = false
		}
	}

	// 状态更新
	if ready {
		gameMatchDataObj.State = entity.WaitVocationStage
	} else {
		return gameMatchDataObj, fmt.Errorf("有玩家未准备，全部准备后开始选庄闲")
	}

	GameMatch.Store(gameKey, gameMatchDataObj)
	return gameMatchDataObj, nil
}

// 选择庄闲  传入的用户id是庄家，其他玩家是闲家
func SetVocation(gameId, userId int64) (*entity.GameMatch, error) {

	gameMatchDataObj := &entity.GameMatch{}

	gameKey := utils.AnyToString(gameId)
	gameMatchData, ok := GameMatch.Load(gameKey)
	if !ok {
		return gameMatchDataObj, fmt.Errorf("本局游戏已结束")
	}
	gameMatchDataObj, ok = gameMatchData.(*entity.GameMatch)
	if !ok {
		return gameMatchDataObj, fmt.Errorf("本局游戏已结束")
	}

	for i := 0; i < len(gameMatchDataObj.UserList); i++ {
		if gameMatchDataObj.UserList[i].UserId == userId {
			gameMatchDataObj.UserList[i].Vocation = 1
		} else {
			gameMatchDataObj.UserList[i].Vocation = 2
		}
	}

	// 选完庄就是等待发牌状态
	gameMatchDataObj.State = entity.WaitDealStage

	GameMatch.Store(gameKey, gameMatchDataObj)
	return gameMatchDataObj, nil
}

// 发牌 新的一轮游戏; 只能庄家调用，调用一次即可，本轮自动开始
func Deal(gameId int64) (*entity.GameMatch, error) {
	gameMatchDataObj := &entity.GameMatch{}
	gameKey := utils.AnyToString(gameId)
	gameMatchData, ok := GameMatch.Load(gameKey)
	if !ok {
		return gameMatchDataObj, fmt.Errorf("本局游戏已结束")
	}
	gameMatchDataObj, ok = gameMatchData.(*entity.GameMatch)
	if !ok {
		return gameMatchDataObj, fmt.Errorf("本局游戏已结束")
	}

	// 新的一轮
	gameMatchDataObj.PlayCount++

	nowT := time.Now().Unix()
	operateStart := nowT + 1
	operateEnd := operateStart + 10 // 操作下注10秒
	lookStart := operateEnd + 1
	lookEnd := lookStart + 30 // 看牌20秒

	gameMatchDataObj.Item = &entity.GameMatchItem{
		Poker:        entity.NewPoker(),                         // 这轮游戏的一幅牌
		UserMap:      make(map[int64]*entity.GameMatchItemUser), // 每个用户的信息
		LookStart:    lookStart,                                 // 用户看牌的开始时间戳
		LookEnd:      lookEnd,                                   // 用户看牌的结算时间戳
		OperateStart: operateStart,                              // 用户操作阶段的开始时间戳
		OperateEnd:   operateEnd,                                // 用户操作阶段的结束的时间
	}

	for _, v := range gameMatchDataObj.UserList {
		pokerData := gameMatchDataObj.Item.Poker[:5] // 玩家的牌

		entity.PrintPoker(pokerData)

		gameMatchDataObj.Item.Poker = gameMatchDataObj.Item.Poker[5 : len(gameMatchDataObj.Item.Poker)-1]

		log.Info("牌长度 : ", len(gameMatchDataObj.Item.Poker))

		gameMatchDataObj.Item.UserMap[v.UserId] = &entity.GameMatchItemUser{
			UserId:      v.UserId,
			NickName:    v.NickName,
			Vocation:    v.Vocation,
			Poker:       pokerData,
			PokerShow:   pokerData,
			Bet:         make([]int64, 0), // 本轮的下注
			IsSurrender: 0,
			PokerResult: new(dao.RuleDao).GetDouNiuResult(pokerData),
		}
	}

	// 发完牌就是下注，看牌，结算依次状态
	gameMatchDataObj.State = entity.BetStage

	GameMatch.Store(gameKey, gameMatchDataObj)
	return gameMatchDataObj, nil
}

// 下注
func Bet(gameId, userId, bet int64) (*entity.GameMatch, error) {
	gameMatchDataObj := &entity.GameMatch{}
	gameKey := utils.AnyToString(gameId)
	gameMatchData, ok := GameMatch.Load(gameKey)
	if !ok {
		return gameMatchDataObj, fmt.Errorf("本局游戏已结束")
	}
	gameMatchDataObj, ok = gameMatchData.(*entity.GameMatch)
	if !ok {
		return gameMatchDataObj, fmt.Errorf("本局游戏已结束")
	}

	for _, v := range gameMatchDataObj.Item.UserMap {
		if v.UserId == userId {
			v.Bet = append(v.Bet, bet)
			break
		}
	}

	GameMatch.Store(gameKey, gameMatchDataObj)
	return gameMatchDataObj, nil
}

// 投降
func Surrender(gameId, userId int64) (*entity.GameMatch, error) {
	gameMatchDataObj := &entity.GameMatch{}
	gameKey := utils.AnyToString(gameId)
	gameMatchData, ok := GameMatch.Load(gameKey)
	if !ok {
		return gameMatchDataObj, fmt.Errorf("本局游戏已结束")
	}
	gameMatchDataObj, ok = gameMatchData.(*entity.GameMatch)
	if !ok {
		return gameMatchDataObj, fmt.Errorf("本局游戏已结束")
	}

	for _, v := range gameMatchDataObj.Item.UserMap {
		if v.UserId == userId {
			v.IsSurrender = 1 // 是否投降   1:投降  非1:没投降
		}
	}

	GameMatch.Store(gameKey, gameMatchDataObj)
	return gameMatchDataObj, nil
}

// 实时获取当前游戏状态
func NowGameState(gameId, roomId int64) (*entity.GameStateData, error) {

	stateData := &entity.GameStateData{
		RoomId:       roomId,
		State:        entity.NoneStage,
		Scoreboard:   make([]*entity.UserScoreboardData, 0),
		UserListInfo: make([]*entity.UserInfo, 0),
		UserBet:      make([]*entity.BetInfo, 0),
		UserPoker:    make([]*entity.UserPokerInfo, 0),
	}

	// 获取房间数据
	roomData, err := RoomData(roomId)
	if err != nil {
		log.Error("获取房间数据失败", err)
		return nil, err
	}

	userBaseInfo := make(map[int64]*entity.UserInfo)

	for _, v := range roomData.UserList {
		isMaster := 0
		if v.UserId == roomData.Homeowner {
			isMaster = 1
		}
		userInfo := &entity.UserInfo{
			UserId:   v.UserId,
			NickName: v.NickName,
			Avatar:   v.Avatar,
			IsMaster: int64(isMaster), // 1:是房主
		}
		stateData.UserListInfo = append(stateData.UserListInfo, userInfo)
		userBaseInfo[v.UserId] = userInfo
	}

	log.Debug("房间状态", roomData.State)

	// 如果房间解散直接返回解散状态
	if roomData.State == -1 {
		stateData.State = -1
		return stateData, nil
	}

	// 强制在房间里找游戏id, 每局会新生成游戏对象，删除旧的
	gameId = RoomGetGameId(roomId)

	gameMatchDataObj := &entity.GameMatch{}
	gameKey := utils.AnyToString(gameId)
	gameMatchData, ok := GameMatch.Load(gameKey)
	if !ok {
		return stateData, fmt.Errorf("本局游戏已结束或未开始")
	}
	gameMatchDataObj, ok = gameMatchData.(*entity.GameMatch)
	if !ok {
		return stateData, fmt.Errorf("本局游戏已结束或未开始")
	}

	// 如果是解散状态 直接返回解散状态
	if gameMatchDataObj.State == -1 {
		stateData.State = -1
		return stateData, nil
	}

	// 游戏信息
	stateData.GameId = gameMatchDataObj.GameId
	stateData.Item = gameMatchDataObj.PlayCount

	// 玩家的准备信息
	userReady := make(map[int64]bool)
	for _, v := range gameMatchDataObj.Ready {
		userReady[v.UserId] = v.IsReady
	}
	for i := 0; i < len(stateData.UserListInfo); i++ {
		if v, o := userReady[stateData.UserListInfo[i].UserId]; v && o {
			stateData.UserListInfo[i].IsReady = 1
		} else {
			stateData.UserListInfo[i].IsReady = 0
		}
	}

	userVocationMap := make(map[int64]int64)
	for _, v := range gameMatchDataObj.UserList {
		// 累计分数信息
		stateData.Scoreboard = append(stateData.Scoreboard, &entity.UserScoreboardData{
			UserId: v.UserId,
			Score:  v.Score,
		})
		// 庄闲信息
		if v.Vocation == 1 {
			stateData.VocationUserId = v.UserId
			stateData.VocationNickName = v.NickName
			userVocationMap[v.UserId] = 1
		} else {
			userVocationMap[v.UserId] = 2
		}
	}
	// 庄闲数据写入
	for i := 0; i < len(stateData.UserListInfo); i++ {
		if v, o := userVocationMap[stateData.UserListInfo[i].UserId]; o {
			stateData.UserListInfo[i].Vocation = v
		}
	}

	// 牌数据和下注数据
	for _, v := range gameMatchDataObj.Item.UserMap {
		userPokerInfo := &entity.UserPokerInfo{
			UserId:      v.UserId,
			Poker:       v.PokerShow,
			PokerResult: v.PokerResult,
		}

		if uInfo, has := userBaseInfo[v.UserId]; has {
			userPokerInfo.NickName = uInfo.NickName
			userPokerInfo.Avatar = uInfo.Avatar
		}

		// 扑克信息
		stateData.UserPoker = append(stateData.UserPoker, userPokerInfo)

		// 下注信息
		stateData.UserBet = append(stateData.UserBet, &entity.BetInfo{
			UserId:   v.UserId,
			NickName: v.NickName,
			BetList:  v.Bet,
		})
	}

	// 触发 操作下注, 看牌，结算 状态的变更
	nowT := time.Now().Unix()

	switch gameMatchDataObj.State {

	case entity.BetStage: // 下注阶段读秒
		if gameMatchDataObj.Item.OperateEnd < nowT {
			gameMatchDataObj.State = entity.LookStage
		} else {
			stateData.Remainder = gameMatchDataObj.Item.OperateEnd - nowT
		}

	case entity.LookStage: // 看牌阶段读秒
		if gameMatchDataObj.Item.LookEnd < nowT {
			gameMatchDataObj.State = entity.BalanceStage
		} else {
			stateData.Remainder = gameMatchDataObj.Item.LookEnd - nowT
		}

	case entity.NextStage: // 本轮结束看结果读秒
		if gameMatchDataObj.Item.ResultEnd < nowT {

			// 一局游戏有10轮 10轮完就结束; 否则开始新的一轮
			if gameMatchDataObj.PlayCount >= 10 {
				gameMatchDataObj.State = entity.EndStage
				gameMatchDataObj.Item.EndGameStart = nowT + 1
				gameMatchDataObj.Item.EndGameEnd = gameMatchDataObj.Item.EndGameStart + 10
			} else {
				gameMatchDataObj.State = entity.WaitDealStage
			}

		} else {
			stateData.Remainder = gameMatchDataObj.Item.ResultEnd - nowT
		}

	case entity.EndStage: // 本局游戏结束看结果读秒
		if gameMatchDataObj.Item.EndGameEnd < nowT { // 新的一局游戏 状态变为1
			// 创建新的游戏， 房间对象的游戏id切换
			_, err := NewGameMatch(roomId)
			if err != nil {
				return nil, err
			}
			GameMatch.Delete(gameKey)
			return stateData, nil

		} else {
			stateData.Remainder = gameMatchDataObj.Item.ResultEnd - nowT
		}

	default:

	}

	GameMatch.Store(gameKey, gameMatchDataObj)

	stateData.State = gameMatchDataObj.State

	// 结算状态触发执行结算
	if gameMatchDataObj.State == entity.BalanceStage && !gameMatchDataObj.BalanceLock {
		gameMatchDataObj.BalanceLock = true

		// 检查投注，如果没投注，默认投注分数是1
		for _, v := range gameMatchDataObj.Item.UserMap {
			if v.Vocation == 2 && len(v.Bet) == 0 {
				v.Bet = append(v.Bet, 1)
			}
		}

		GameMatch.Store(gameKey, gameMatchDataObj)

		_, _ = Balance(gameMatchDataObj.GameId)
	}

	return stateData, nil
}

// 结算
func Balance(gameId int64) (*entity.GameMatch, error) {
	gameMatchDataObj := &entity.GameMatch{}
	gameKey := utils.AnyToString(gameId)
	gameMatchData, ok := GameMatch.Load(gameKey)
	if !ok {
		return gameMatchDataObj, fmt.Errorf("本局游戏已结束")
	}
	gameMatchDataObj, ok = gameMatchData.(*entity.GameMatch)
	if !ok {
		return gameMatchDataObj, fmt.Errorf("本局游戏已结束")
	}

	// 计算每个玩家的牌型
	for _, v := range gameMatchDataObj.Item.UserMap {
		v.PokerResult = new(dao.RuleDao).GetDouNiuResult(v.Poker)
	}

	// 庄家
	master := &entity.GameMatchItemUser{}
	// 闲加
	slaveList := make([]*entity.GameMatchItemUser, 0)

	for _, v := range gameMatchDataObj.Item.UserMap {
		// 1:庄  2:闲
		if v.Vocation == 1 {
			master = v
		}
		if v.Vocation == 2 {
			slaveList = append(slaveList, v)
		}
	}

	// 比牌，结算并记录
	for _, slave := range slaveList {

		// 倍数
		multiple := 1

		// 结算时间
		nowT := time.Now().Unix()

		// 庄家闲家牌json字符串
		pokerJsonStrMaster, _ := json.Marshal(master.Poker)
		pokerResultJsonMaster, _ := json.Marshal(master.PokerResult)
		pokerJsonStrSlave, _ := json.Marshal(slave.Poker)
		pokerResultJsonSlave, _ := json.Marshal(slave.PokerResult)

		// 结果 庄家赢 庄家加分 闲家减分
		rse := new(dao.RuleDao).DouNiuContrast(master.PokerResult, slave.PokerResult)
		slaveBet := sum(gameMatchDataObj.Item.UserMap[slave.UserId].Bet)
		if rse {
			// 计算倍数  0:无牛  1:有牛  2:牛牛  3:五小  4:银牛  5:金牛  6:炸弹
			switch master.PokerResult.HasNiu {
			case 0:
			case 1:
				// 有牛：7,8,9点2倍，其他点数1倍
				if master.PokerResult.NiuNum >= 7 {
					multiple = 2
				}
			case 2, 3, 4, 5, 6:
				multiple = 3
			default:
			}

			score := slaveBet * int64(multiple)
			gameMatchDataObj.Item.UserMap[master.UserId].Score += score
			gameMatchDataObj.Item.UserMap[master.UserId].Multiple = int64(multiple)
			// 本局游戏输赢分数累计
			var sumScoreMaster int64 = 0
			for i := 0; i < len(gameMatchDataObj.UserList); i++ {
				if gameMatchDataObj.UserList[i].UserId == master.UserId {
					gameMatchDataObj.UserList[i].Score += score
					sumScoreMaster = gameMatchDataObj.UserList[i].Score
				}
			}
			// 记录比牌结果 - master
			_ = new(dao.GameDao).BalanceRecord(&entity.UserGameItemInfo{
				UserId:           master.UserId,                 // 玩家id
				GameId:           gameMatchDataObj.GameId,       // 游戏对局id
				ItemId:           gameMatchDataObj.PlayCount,    // 游戏轮数id
				Bet:              0,                             // 玩家的投注信息
				State:            1,                             // 输赢状态  1:赢  非1:输
				Balance:          slaveBet,                      // 本轮玩家结算
				Score:            score,                         // 本轮游戏的输赢分
				AllScore:         sumScoreMaster,                // 本局游戏总输赢累计分
				Vocation:         1,                             // 玩家庄闲  1:庄  2:闲
				CreatedAt:        nowT,                          // 结算时间s
				Poker:            string(pokerJsonStrMaster),    // 玩家的牌信息 json
				PokerResult:      string(pokerResultJsonMaster), // 玩家牌型 json
				RivalId:          slave.UserId,                  // 对手id
				RivalVocation:    2,                             // 对手庄闲  1:庄  2:闲
				RivalPoker:       string(pokerJsonStrSlave),     // 对手牌信息 json
				RivalPokerResult: string(pokerResultJsonSlave),  // 对手牌型 json
				VSMsg:            "庄家胜",                         // 对局结构消息
				Multiple:         int64(multiple),               // 对局输赢倍数
			})

			gameMatchDataObj.Item.UserMap[slave.UserId].Score -= score
			gameMatchDataObj.Item.UserMap[slave.UserId].Multiple = int64(multiple)
			// 本局游戏输赢分数累计 - slave
			var sumScoreSlave int64 = 0
			for i := 0; i < len(gameMatchDataObj.UserList); i++ {
				if gameMatchDataObj.UserList[i].UserId == slave.UserId {
					gameMatchDataObj.UserList[i].Score -= score
					sumScoreSlave = gameMatchDataObj.UserList[i].Score
				}
			}
			// 记录比牌结果 - slave
			_ = new(dao.GameDao).BalanceRecord(&entity.UserGameItemInfo{
				UserId:           slave.UserId,                  // 玩家id
				GameId:           gameMatchDataObj.GameId,       // 游戏对局id
				ItemId:           gameMatchDataObj.PlayCount,    // 游戏轮数id
				Bet:              slaveBet,                      // 玩家的投注信息
				State:            2,                             // 输赢状态  1:赢  非1:输
				Balance:          -slaveBet,                     // 本轮玩家结算
				Score:            -score,                        // 本轮游戏的输赢分
				AllScore:         sumScoreSlave,                 // 本局游戏总输赢累计分
				Vocation:         2,                             // 玩家庄闲  1:庄  2:闲
				CreatedAt:        nowT,                          // 结算时间s
				Poker:            string(pokerJsonStrSlave),     // 玩家的牌信息 json
				PokerResult:      string(pokerResultJsonSlave),  // 玩家牌型 json
				RivalId:          master.UserId,                 // 对手id
				RivalVocation:    1,                             // 对手庄闲  1:庄  2:闲
				RivalPoker:       string(pokerJsonStrMaster),    // 对手牌信息 json
				RivalPokerResult: string(pokerResultJsonMaster), // 对手牌型 json
				VSMsg:            "庄家胜",                         // 对局结构消息
				Multiple:         int64(multiple),               // 对局输赢倍数
			})

		} else {
			// 0:无牛  1:有牛  2:牛牛  3:五小  4:银牛  5:金牛  6:炸弹
			switch slave.PokerResult.HasNiu {
			case 0:
			case 1:
				// 有牛：7,8,9点2倍，其他点数1倍
				if slave.PokerResult.NiuNum >= 7 {
					multiple = 2
				}
			case 2, 3, 4, 5, 6:
				multiple = 3
			default:
			}

			score := slaveBet * int64(multiple)

			gameMatchDataObj.Item.UserMap[master.UserId].Score -= score
			gameMatchDataObj.Item.UserMap[master.UserId].Multiple = int64(multiple)

			// 本局游戏输赢分数累计
			var sumScoreMaster int64 = 0
			for i := 0; i < len(gameMatchDataObj.UserList); i++ {
				if gameMatchDataObj.UserList[i].UserId == master.UserId {
					gameMatchDataObj.UserList[i].Score -= score
					sumScoreMaster = gameMatchDataObj.UserList[i].Score
				}
			}
			// 记录比牌结果 - master
			_ = new(dao.GameDao).BalanceRecord(&entity.UserGameItemInfo{
				UserId:           master.UserId,                 // 玩家id
				GameId:           gameMatchDataObj.GameId,       // 游戏对局id
				ItemId:           gameMatchDataObj.PlayCount,    // 游戏轮数id
				Bet:              0,                             // 玩家的投注信息
				State:            2,                             // 输赢状态  1:赢  非1:输
				Balance:          -slaveBet,                     // 本轮玩家结算
				Score:            -score,                        // 本轮游戏的输赢分
				AllScore:         sumScoreMaster,                // 本局游戏总输赢累计分
				Vocation:         1,                             // 玩家庄闲  1:庄  2:闲
				CreatedAt:        nowT,                          // 结算时间s
				Poker:            string(pokerJsonStrMaster),    // 玩家的牌信息 json
				PokerResult:      string(pokerResultJsonMaster), // 玩家牌型 json
				RivalId:          slave.UserId,                  // 对手id
				RivalVocation:    2,                             // 对手庄闲  1:庄  2:闲
				RivalPoker:       string(pokerJsonStrSlave),     // 对手牌信息 json
				RivalPokerResult: string(pokerResultJsonSlave),  // 对手牌型 json
				VSMsg:            "闲家胜",                         // 对局结构消息
				Multiple:         int64(multiple),               // 对局输赢倍数
			})

			gameMatchDataObj.Item.UserMap[slave.UserId].Score += score
			gameMatchDataObj.Item.UserMap[slave.UserId].Multiple = int64(multiple)

			// 本局游戏输赢分数累计 - slave
			var sumScoreSlave int64 = 0
			for i := 0; i < len(gameMatchDataObj.UserList); i++ {
				if gameMatchDataObj.UserList[i].UserId == slave.UserId {
					gameMatchDataObj.UserList[i].Score += score
					sumScoreSlave = gameMatchDataObj.UserList[i].Score
				}
			}
			// 记录比牌结果 - slave
			_ = new(dao.GameDao).BalanceRecord(&entity.UserGameItemInfo{
				UserId:           slave.UserId,                  // 玩家id
				GameId:           gameMatchDataObj.GameId,       // 游戏对局id
				ItemId:           gameMatchDataObj.PlayCount,    // 游戏轮数id
				Bet:              slaveBet,                      // 玩家的投注信息
				State:            1,                             // 输赢状态  1:赢  非1:输
				Balance:          slaveBet,                      // 本轮玩家结算
				Score:            score,                         // 本轮游戏的输赢分
				AllScore:         sumScoreSlave,                 // 本局游戏总输赢累计分
				Vocation:         2,                             // 玩家庄闲  1:庄  2:闲
				CreatedAt:        nowT,                          // 结算时间s
				Poker:            string(pokerJsonStrSlave),     // 玩家的牌信息 json
				PokerResult:      string(pokerResultJsonSlave),  // 玩家牌型 json
				RivalId:          master.UserId,                 // 对手id
				RivalVocation:    1,                             // 对手庄闲  1:庄  2:闲
				RivalPoker:       string(pokerJsonStrMaster),    // 对手牌信息 json
				RivalPokerResult: string(pokerResultJsonMaster), // 对手牌型 json
				VSMsg:            "闲家胜",                         // 对局结构消息
				Multiple:         int64(multiple),               // 对局输赢倍数
			})

		}

	}

	// 给10秒的结果查询时间
	gameMatchDataObj.Item.ResultStart = time.Now().Unix() + 1
	gameMatchDataObj.Item.ResultEnd = gameMatchDataObj.Item.ResultStart + 10

	gameMatchDataObj.BalanceLock = false // 结算完了释放锁
	gameMatchDataObj.State = entity.NextStage
	GameMatch.Store(gameKey, gameMatchDataObj)

	// 更新游戏状态中的数据

	return gameMatchDataObj, nil
}

func sum(bet []int64) int64 {
	var s int64 = 0
	for _, v := range bet {
		s += v
	}
	return s
}

// 变牌
func ChangePoker(gameId, userId, niuType int64) (*entity.GameMatch, []*entity.PokerData, error) {
	result := make([]*entity.PokerData, 0)
	gameMatchDataObj := &entity.GameMatch{}
	gameKey := utils.AnyToString(gameId)
	gameMatchData, ok := GameMatch.Load(gameKey)
	if !ok {
		return gameMatchDataObj, result, fmt.Errorf("本局游戏已结束")
	}
	gameMatchDataObj, ok = gameMatchData.(*entity.GameMatch)
	if !ok {
		return gameMatchDataObj, result, fmt.Errorf("本局游戏已结束")
	}

	for k, v := range gameMatchDataObj.Item.UserMap {
		if k == userId {
			newPoker, has := new(dao.RuleDao).ChangeDouNiuPoker(gameMatchDataObj.Item.Poker, niuType)
			if !has {
				return gameMatchDataObj, result, fmt.Errorf("剩余牌无法组成这个类型，请重新选择")
			}
			v.Poker = newPoker
			v.PokerShow = newPoker
			result = v.Poker
		}
	}
	GameMatch.Store(gameKey, gameMatchDataObj)
	return gameMatchDataObj, result, nil
}

// 解散房间用
func SetGameMatchStateDissolution(gameId int64) {
	gameMatchDataObj := &entity.GameMatch{}
	gameKey := utils.AnyToString(gameId)
	gameMatchData, ok := GameMatch.Load(gameKey)
	if !ok {
		log.ErrorF("本局游戏已结束")
		return
	}
	gameMatchDataObj, ok = gameMatchData.(*entity.GameMatch)
	if !ok {
		log.ErrorF("本局游戏已结束")
		return
	}
	gameMatchDataObj.State = -1
	GameMatch.Store(gameKey, gameMatchDataObj)
	return
}
